查看原文
其他

Android NDK层编译OpenCV代码开发详解

gloomyfish OpenCV学堂 2019-03-29

Android NDK层编译OpenCV代码开发详解

使用Android NDK开发编译OpenCV C++代码,这个在OpenCV4Android开发中会经常遇到的要求,因为OpenCV4Android SDK多数Java代码都是基于JNI调用,如果对于实时性与应用要求比较高的场合来说,多次频繁调用JNI层本身就会导致很大的资源开销,这个时候就需要将全部的处理封装在C++层,在C++中调用OpenCV相关API函数,同时通过在JNI层面定义本地方法,力争做到每次处理图像,只调用JNI一次,这样就会达到比较高的运行速度与好的用户体验。下面我们就从OpenCV4Android SDK与Android NDK开发环境搭建,OpenCV C++程序实现,编译完成与运行各个环节介绍如何在Android NDK层面编译OpenCV C++代码实现JNI调用。

一:环境搭建

首先下载Android Studio与Android SDK,在Android Studio中创建一个新项目,然后参照【OpenCV学堂】之前的文章《OpenCv3.2集成Android Studio开发配置》完成OpenCV4Android开发环境搭建即可。

二:JNI接口定义

在MainActivity中添加一个native本地方法即可

  1. public native void convertGray(long srcAddress, long dstAddress);

三:OpenCV C++代码实现

然后在app/src下面新建一个目录jni,然后创建一个cpp源文件,把下面的代码copy到其中保存

  1. #include<jni.h>

  2. #include<opencv2/opencv.hpp>

  3. #include <iostream>

  4. #include<vector>

  5. #include <android/log.h>

  6. #define  LOG_TAG    "MYOPENCV_TEST"

  7. #define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)

  8. #define  LOGW(...)  __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__)

  9. #define  LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)

  10. #define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)

  11. using namespace cv;

  12. using namespace std;

  13. extern"C" {

  14.    JNIEXPORT void JNICALL Java_com_example_zhigang_myapplication_MainActivity_convertGray(JNIEnv* env, jobject, jlong srcAddress, jlong dstAddress)

  15.    {

  16.        Mat& src = *(Mat*)srcAddress;

  17.        Mat& dst = *(Mat*)dstAddress;

  18.        cvtColor(src, dst, COLOR_BGR2GRAY);

  19.        LOGD( "Method Description: %s", "convert to gray image..." );

  20.    }

  21. }

其中com.example.zhigang.myapplication.MainActivity表示当前MainActivity完整的包路径。定义的JNI方法为convertGray,两个参数分别是源图像的地址与输出的灰度图像的地址,实现的功能是把彩色图像转换为灰度图像。

四:编译运行

上述代码要想完整的编译与运行,需要创建两个文件Android.mk与Application.mk文件,然后把下面的内容copy到Android.mk中去:

  1. LOCAL_PATH := $(call my-dir)

  2. include $(CLEAR_VARS)

  3. OPENCV_CAMERA_MODULES:=on

  4. OPENCV_INSTALL_MODULES:=on

  5. include D:/opencv-3.3/opencv/android/install/sdk/native/jni/OpenCV.mk

  6. LOCAL_MODULE := gray_converter

  7. LOCAL_SRC_FILES := gray_mat.cpp

  8. LOCAL_LDLIBS += -llog -ldl

  9. include $(BUILD_SHARED_LIBRARY)

其中include的路径是你OpenCV4Android SDK实际所在的路径,然后把下面内容copy到Application.mk中去:

  1. APP_STL := gnustl_static

  2. APP_CPPFLAGS := -frtti -fexceptions

  3. APP_ABI := armeabi-v7a

  4. APP_PLATFORM := android-14

然后对当前项目添加NDK支持,打开cmd,切换到src/jni目录,然后运行下面的命令行: /ndk-build 即可完成编译,生成的so文件copy到app/libs中去即可,然后就可以在MainActivity的onCreate方法中通过如下代码加载库文件, System.loadLibrary("gray_converter"); 然后就可以参考上面提到文章调用完成代码演示即可。代码如下:

  1. private void convertGray() {

  2.    Mat src = new Mat();

  3.    Mat temp = new Mat();

  4.    Mat dst = new Mat();

  5.    Bitmap image = BitmapFactory.decodeResource(this.getResources(), R.drawable.lena);

  6.    Utils.bitmapToMat(image, src);

  7.    Imgproc.cvtColor(src, temp, Imgproc.COLOR_RGBA2BGR);

  8.    Log.i("CV", "image type:" + (temp.type() == CvType.CV_8UC3));

  9.    //Imgproc.cvtColor(temp, dst, Imgproc.COLOR_BGR2GRAY);

  10.    convertGray(temp.getNativeObjAddr(), dst.getNativeObjAddr());

  11.    Utils.matToBitmap(dst, image);

  12.    ImageView imageView = (ImageView)findViewById(R.id.image_lena);

  13.    imageView.setImageBitmap(image);

  14.    // release memory

  15.    src.release();

  16.    temp.release();

  17.    dst.release();

  18. }


最终运行结果:



学而不化,非学也


关注【OpenCV学堂】

长按或者扫码下面二维码即可关注

+OpenCV学习群 376281510

进群暗号:OpenCV


    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存